// Kony


#include "AbilitySystem/AsyncTasks/WaitCooldownChange.h"
#include "AbilitySystemComponent.h"
//创建异步任务 赋值
UWaitCooldownChange* UWaitCooldownChange::WaitForCooldownChange(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayTag& InCooldownTag)
{
	UWaitCooldownChange* WaitCooldownChange = NewObject<UWaitCooldownChange>();
	WaitCooldownChange->ASC = AbilitySystemComponent;
	WaitCooldownChange->CooldownTag = InCooldownTag;
	//判断如果ASC和CooldownTag不合法，结束任务
	if (!IsValid(WaitCooldownChange) || !InCooldownTag.IsValid())
	{
		WaitCooldownChange->EndTask();
		return nullptr;
	}
	//注册CooldownTag的回调函数，冷却标签改变时候触发
	//冷却何时结束（冷却标签已被移除）
	AbilitySystemComponent->RegisterGameplayTagEvent(
		InCooldownTag,
		EGameplayTagEventType::NewOrRemoved).AddUObject(
			WaitCooldownChange,
			&UWaitCooldownChange::CooldownTagChanged);
	//这个在服务端和客户端都会触发，执行广播
	//何时应用了冷却效果（施加了冷却标签）
	AbilitySystemComponent->OnActiveGameplayEffectAddedDelegateToSelf.AddUObject(
		WaitCooldownChange,
		&UWaitCooldownChange::OnActiveEffectAdded);
	return WaitCooldownChange;
	
}
//结束任务 销毁数据
void UWaitCooldownChange::EndTask()
{
	if (!IsValid(ASC)) return;
	//移除注册的回调函数
	ASC->RegisterGameplayTagEvent(CooldownTag, EGameplayTagEventType::NewOrRemoved).RemoveAll(this);
	//设置准备销毁
	SetReadyToDestroy();
	//标记垃圾回收
	MarkAsGarbage();
}
//冷却时间标签更变时（也就是施加冷却时间，移除冷却时间标签时触发）
void UWaitCooldownChange::CooldownTagChanged(const FGameplayTag InCooldownTag, int32 NewCount)
{
	//冷却结束时，触发广播事件
	if (NewCount == 0)
	{
		CooldownEnd.Broadcast(0.f);
	}
	
}
//OnActiveGameplayEffectAddedDelegateToSelf 委托的回调函数
void UWaitCooldownChange::OnActiveEffectAdded(UAbilitySystemComponent* TargetASC, const FGameplayEffectSpec& SpecApplied, FActiveGameplayEffectHandle ActiveEffectHandle)
{
	FGameplayTagContainer AssetTags;
	//获取能力效果施加的所有标签
	SpecApplied.GetAllAssetTags(AssetTags);
	//判断施加的标签是否包含CooldownTag
	FGameplayTagContainer GranteTags;
	SpecApplied.GetAllGrantedTags(GranteTags);
	//如果任意一个包含了冷却标签，则说明技能在冷却中
	if (AssetTags.HasTagExact(CooldownTag) || GranteTags.HasTagExact(CooldownTag))
	{
		//匹配是否有特定冷却标签
		FGameplayEffectQuery GameplayEffectQuery = FGameplayEffectQuery::MakeQuery_MatchAnyOwningTags(CooldownTag.GetSingleTagContainer());
		//可返回所有匹配的冷却标签，冷却时间 的数组，但目前只用1个冷却标签，所以只取第一个
		TArray<float> TimesRemaining = ASC->GetActiveEffectsTimeRemaining(GameplayEffectQuery);
		if (TimesRemaining.Num() > 0)
		{
			//当前冷却时间最长的标签，先设置第一个，如果有比第一个大的，就替换掉
			float TimeRemaining = TimesRemaining[0];
			for (int32 i = 1; i < TimesRemaining.Num(); i++)
			{
				if (TimesRemaining[i] > TimeRemaining)
				{
					TimeRemaining = TimesRemaining[i];
				}
			}
			//触发广播冷却开始事件
			CooldownStart.Broadcast(TimeRemaining);
		}
	}
}
